const fs = require('fs');
const { Ogg } = require('@vocaltale/opus.js');

// Opus标准参数配置
const DEFAULT_SAMPLE_RATE = 48000;  // Opus解码后的标准采样率
const DEFAULT_CHANNELS = 1;         // 单声道
const DEFAULT_FRAME_SIZE = 960;     // 48kHz × 20ms = 960样本
const DEFAULT_SERIAL_NUMBER = 1;

function saveOpusOgg(filePath, buffer, audioParams = null) {
    try {
        console.log(`收到的buffer总大小: ${buffer.length} 字节`);
        console.log(`Buffer前32字节的十六进制: ${buffer.subarray(0, Math.min(32, buffer.length)).toString('hex')}`);
        console.log(`Buffer前32字节的ASCII: ${buffer.subarray(0, Math.min(32, buffer.length)).toString('ascii').replace(/[^\x20-\x7E]/g, '.')}`);

        // 更详细的OGG格式检测
        let isOggFormat = false;
        let detectionMethod = '';

        // 检查是否以OggS开头
        if (buffer.length >= 4 && buffer.subarray(0, 4).toString('ascii') === 'OggS') {
            isOggFormat = true;
            detectionMethod = 'OggS魔术字节';
        }
        // 检查是否包含OpusHead
        else if (buffer.includes(Buffer.from('OpusHead'))) {
            isOggFormat = true;
            detectionMethod = 'OpusHead标识符';
        }
        // 检查是否包含OpusTags
        else if (buffer.includes(Buffer.from('OpusTags'))) {
            isOggFormat = true;
            detectionMethod = 'OpusTags标识符';
        }

        if (isOggFormat) {
            console.log(`检测到buffer已经是OGG格式 (通过: ${detectionMethod})`);

            // 分析OGG页面结构
            let offset = 0;
            let pageCount = 0;
            while (offset < buffer.length - 4) {
                if (buffer.subarray(offset, offset + 4).toString('ascii') === 'OggS') {
                    pageCount++;
                    console.log(`找到OGG页面 ${pageCount} 在偏移量 ${offset}`);

                    if (offset + 26 < buffer.length) {
                        const pageSegments = buffer[offset + 26];
                        console.log(`  页面段数: ${pageSegments}`);

                        // 跳过页面头部（27字节）和段表
                        let segmentTableOffset = offset + 27;
                        let totalSegmentSize = 0;
                        for (let i = 0; i < pageSegments && segmentTableOffset + i < buffer.length; i++) {
                            totalSegmentSize += buffer[segmentTableOffset + i];
                        }
                        offset = segmentTableOffset + pageSegments + totalSegmentSize;
                        console.log(`  页面总大小: ${offset - (offset - 27 - pageSegments - totalSegmentSize)} 字节`);
                    } else {
                        break;
                    }
                } else {
                    offset++;
                }
            }

            console.log(`原始buffer大小: ${buffer.length} 字节, 包含 ${pageCount} 个OGG页面`);

            // 先尝试重建OGG文件（提取音频帧并重新封装）
            console.log('尝试重建OGG文件以确保正确的结构...');
            const rebuildSuccess = rebuildOggFile(filePath, buffer, audioParams);

            if (!rebuildSuccess) {
                console.log('重建失败，回退到直接写入原始数据');
                fs.writeFileSync(filePath, buffer);
                console.log(`OGG文件已直接保存到: ${filePath}`);
            }

            return true;
        }

        // 使用传入的音频参数，或者使用默认值
        const sampleRate = audioParams?.sample_rate || DEFAULT_SAMPLE_RATE;
        const channels = audioParams?.channels || DEFAULT_CHANNELS;
        const frameSize = audioParams?.frame_size || DEFAULT_FRAME_SIZE;
        const serialNumber = DEFAULT_SERIAL_NUMBER;

        console.log(`使用音频参数: 采样率=${sampleRate}Hz, 声道=${channels}, 帧大小=${frameSize}`);

        // 创建 OGG 容器
        const ogg = new Ogg(sampleRate, channels, frameSize, serialNumber);

        // 创建输出流
        const stream = fs.createWriteStream(filePath);

        // 写入 OGG 头部页面
        const idPage = ogg.generateIdPage();
        const commentPage = ogg.generateCommentPage();
        stream.write(idPage);
        stream.write(commentPage);

        console.log(`头部大小: ID页面=${idPage.length}字节, 注释页面=${commentPage.length}字节`);

        // 检查buffer是否包含长度前缀
        let offset = 0;
        let frameCount = 0;
        let totalFrameBytes = 0;

        // 方法1: 尝试解析带长度前缀的格式
        console.log('\n尝试解析带长度前缀的格式...');
        while (offset < buffer.length) {
            if (offset + 4 > buffer.length) {
                console.log(`在偏移量${offset}处没有足够的字节读取长度信息`);
                break;
            }

            // 尝试Big Endian
            const frameLengthBE = buffer.readUInt32BE(offset);
            // 尝试Little Endian
            const frameLengthLE = buffer.readUInt32LE(offset);

            console.log(`偏移量${offset}: BE长度=${frameLengthBE}, LE长度=${frameLengthLE}`);

            // 合理的Opus帧长度通常在10-4000字节之间
            let frameLength;
            if (frameLengthBE > 0 && frameLengthBE <= 4000 && offset + 4 + frameLengthBE <= buffer.length) {
                frameLength = frameLengthBE;
                console.log(`使用Big Endian长度: ${frameLength}`);
            } else if (frameLengthLE > 0 && frameLengthLE <= 4000 && offset + 4 + frameLengthLE <= buffer.length) {
                frameLength = frameLengthLE;
                console.log(`使用Little Endian长度: ${frameLength}`);
            } else {
                console.log(`无效的帧长度，可能不是带长度前缀的格式`);
                break;
            }

            offset += 4;

            if (offset + frameLength > buffer.length) {
                console.log(`帧长度${frameLength}超出buffer范围`);
                break;
            }

            // 提取 Opus 数据帧
            const opusFrame = buffer.subarray(offset, offset + frameLength);
            offset += frameLength;
            frameCount++;
            totalFrameBytes += frameLength;

            console.log(`帧${frameCount}: 长度=${frameLength}字节, 前8字节=${opusFrame.subarray(0, 8).toString('hex')}`);

            // 将 Opus 帧分段并写入 OGG 页面
            try {
                const packets = ogg.segmentPacket(opusFrame);
                packets.forEach(packet => {
                    stream.write(packet);
                });
            } catch (error) {
                console.error(`处理帧${frameCount}时出错:`, error.message);
            }
        }

        console.log(`\n处理结果: 找到${frameCount}个帧, 总计${totalFrameBytes}字节的Opus数据`);

        // 如果没有找到任何帧，尝试将整个buffer作为单个Opus帧处理
        if (frameCount === 0) {
            console.log('\n尝试将整个buffer作为单个Opus帧处理...');
            try {
                const packets = ogg.segmentPacket(buffer);
                packets.forEach(packet => {
                    stream.write(packet);
                });
                console.log(`成功处理整个buffer作为单个帧`);
            } catch (error) {
                console.error('作为单个帧处理失败:', error.message);
            }
        }

        // 完成并关闭文件
        const finalData = ogg.finalize();
        stream.write(finalData);
        stream.end();

        console.log(`\nOGG 文件已保存到: ${filePath}`);

        // 检查生成的文件大小
        setTimeout(() => {
            try {
                const stats = fs.statSync(filePath);
                console.log(`生成的文件大小: ${stats.size} 字节`);
            } catch (error) {
                console.error('无法检查文件大小:', error);
            }
        }, 100);

        return true;

    } catch (error) {
        console.error('保存 OGG 文件时出错:', error);
        return false;
    }
}

// 新增：处理纯Opus数据的函数（没有长度前缀）
function saveOpusOggRaw(filePath, buffer, audioParams = null) {
    try {
        console.log(`处理纯Opus数据，buffer大小: ${buffer.length} 字节`);

        // 使用传入的音频参数，或者使用默认值
        const sampleRate = audioParams?.sample_rate || DEFAULT_SAMPLE_RATE;
        const channels = audioParams?.channels || DEFAULT_CHANNELS;
        const opusFrameSize = audioParams?.frame_size || DEFAULT_FRAME_SIZE;
        const serialNumber = DEFAULT_SERIAL_NUMBER;

        console.log(`使用音频参数: 采样率=${sampleRate}Hz, 声道=${channels}, 帧大小=${opusFrameSize}`);

        const ogg = new Ogg(sampleRate, channels, opusFrameSize, serialNumber);
        const stream = fs.createWriteStream(filePath);

        // 写入头部
        stream.write(ogg.generateIdPage());
        stream.write(ogg.generateCommentPage());

        // 将整个buffer作为Opus数据处理
        try {
            const packets = ogg.segmentPacket(buffer);
            packets.forEach(packet => {
                stream.write(packet);
            });
            console.log('成功处理纯Opus数据');
        } catch (error) {
            console.error('处理纯Opus数据失败:', error);
        }

        const finalData = ogg.finalize();
        stream.write(finalData);
        stream.end();

        console.log(`纯Opus数据OGG文件已保存到: ${filePath}`);
        return true;

    } catch (error) {
        console.error('处理纯Opus数据时出错:', error);
        return false;
    }
}

// 重新构建OGG文件的函数
function rebuildOggFile(filePath, buffer, audioParams = null) {
    try {
        console.log('尝试重新构建OGG文件结构...');

        // 提取所有Opus帧数据
        const opusFrames = [];
        let offset = 0;

        while (offset < buffer.length - 4) {
            if (buffer.subarray(offset, offset + 4).toString('ascii') === 'OggS') {
                console.log(`处理OGG页面，偏移量: ${offset}`);

                if (offset + 26 >= buffer.length) break;

                const pageSegments = buffer[offset + 26];
                let segmentTableOffset = offset + 27;

                // 读取段表
                const segmentLengths = [];
                for (let i = 0; i < pageSegments && segmentTableOffset + i < buffer.length; i++) {
                    segmentLengths.push(buffer[segmentTableOffset + i]);
                }

                // 跳过头部和段表，提取数据
                let dataOffset = segmentTableOffset + pageSegments;
                for (const segmentLength of segmentLengths) {
                    if (dataOffset + segmentLength <= buffer.length) {
                        const segmentData = buffer.subarray(dataOffset, dataOffset + segmentLength);

                        // 检查是否为音频数据（不是OpusHead或OpusTags）
                        const segmentStr = segmentData.toString('ascii', 0, Math.min(8, segmentData.length));
                        if (!segmentStr.includes('OpusHead') && !segmentStr.includes('OpusTags')) {
                            opusFrames.push(segmentData);
                            console.log(`提取音频帧，大小: ${segmentData.length} 字节`);
                        }

                        dataOffset += segmentLength;
                    }
                }

                // 移动到下一个页面
                offset = dataOffset;
            } else {
                offset++;
            }
        }

        console.log(`提取到 ${opusFrames.length} 个音频帧`);

        if (opusFrames.length === 0) {
            console.log('未找到有效的音频帧，回退到直接写入');
            fs.writeFileSync(filePath, buffer);
            return true;
        }

        // 使用提取的音频帧重新创建OGG文件
        const sampleRate = audioParams?.sample_rate || DEFAULT_SAMPLE_RATE;
        const channels = audioParams?.channels || DEFAULT_CHANNELS;
        const frameSize = audioParams?.frame_size || DEFAULT_FRAME_SIZE;

        const ogg = new Ogg(sampleRate, channels, frameSize, 1);
        const stream = fs.createWriteStream(filePath);

        // 写入头部
        const idPage = ogg.generateIdPage();
        const commentPage = ogg.generateCommentPage();
        stream.write(idPage);
        stream.write(commentPage);

        console.log(`写入头部: ID页面=${idPage.length}字节, 注释页面=${commentPage.length}字节`);

        // 写入音频帧
        for (let i = 0; i < opusFrames.length; i++) {
            try {
                const packets = ogg.segmentPacket(opusFrames[i]);
                packets.forEach(packet => {
                    stream.write(packet);
                });
                console.log(`写入音频帧 ${i + 1}/${opusFrames.length}`);
            } catch (error) {
                console.error(`处理音频帧 ${i + 1} 时出错:`, error.message);
            }
        }

        // 完成文件
        const finalData = ogg.finalize();
        stream.write(finalData);
        stream.end();

        console.log(`重建的OGG文件已保存到: ${filePath}`);
        return true;

    } catch (error) {
        console.error('重建OGG文件失败:', error);
        return false;
    }
}

module.exports = { saveOpusOgg, saveOpusOggRaw, rebuildOggFile };
